/*
*
*	Purpose: to provide wrapper functions useful in Lua
*
*/

#pragma once
#include "Lua.h"
#include "GenericKeys.h"
#include "SuperData.h"
#include "MapManager.hpp"
#include "MapGenerator.h"
#include "ImageLoader.hpp"

/* Comment these lines out to disable visual or execution log debugging */

#ifdef LUA_CONSOLE_DEBUG
#include <iostream>
using namespace std;
#endif

#ifdef LUA_EXECUTE_DEBUG
#include "ExecutionLog.h"
#endif


// Use a namespace to keep the global namespace "clean"
namespace LUA_FUNCTIONS
{
	// An error handling function, for simplicity (checks the number of arguments a function has recieved and gives a warning
	bool CheckArgumentCount(int total_arguments, const char* function_name)
	{
		if(Lua->GetParamaterCount() != total_arguments)
		{
			#ifdef LUA_CONSOLE_DEBUG
			cout << "\nLua Warning - Bad param count passed to " << function_name << "; expected " << total_arguments << endl;
			#endif
			#ifdef LUA_EXECUTE_DEBUG
			Log->AddMessage("Lua Warning - Bad param count passed to a function");
			#endif
			return false;
		}

		//Log->AddMessage("Lua function[ " + GetString(function_name) + " ] called.");
		
		return true;
	}

	// Our wrapper functions

	// Used to display a message from Lua
	LuaGlue l_DisplayMessage (lua_State *L)
	{
		// Error handling (lua handles the rest
		CheckArgumentCount(5, "DisplayMessage");

		Key->GetFont(Lua->GetStringArgument(4, "onuava"))->drawText(Lua->GetNumberArgument(1, 0.0), Lua->GetNumberArgument(2, 0.0),
			Lua->GetStringArgument(3, ""), Key->GetColor(Lua->GetStringArgument(5, "")));


		return 0; // 0 results, needed by lua
	}

	LuaGlue l_GetWindowDimensions(lua_State *L)
	{
		Lua->PushNumber(DataLoader->WINDOW_WIDTH);
		Lua->PushNumber(DataLoader->WINDOW_HEIGHT);

		return 2; // 2 results
	}

	LuaGlue l_GetImageID(lua_State *L)
	{
		if(CheckArgumentCount(1, "GetImageID"))
		{
			Lua->PushNumber(ImageManager->GetImageID(Lua->GetStringArgument(1, "")));
			return 1;
		}

		return 0;
	}


	LuaGlue l_GetFontWidth(lua_State *L)
	{
		if(CheckArgumentCount(2, "GetFontWidth"))
		{
			Lua->PushNumber(Key->GetFont(Lua->GetStringArgument(1, ""))->calcStringWidth(Lua->GetStringArgument(2, "")));
			return 1;
		}
		
		return 0;
	}

	LuaGlue l_GetFontHeight(lua_State *L)
	{
		if(CheckArgumentCount(1, "GetFontHeight"))
		{
			Lua->PushNumber(Key->GetFont(Lua->GetStringArgument(1, ""))->getHeight());
			return 1;
		}
		return 0;
	}

	LuaGlue l_AddMap(lua_State *L)
	{
		CheckArgumentCount(3, "AddMap");
		MapManager::AddMap(Lua->GetStringArgument(1, ""), Lua->GetStringArgument(2, ""), Lua->GetStringArgument(3, ""));

		return 0;
	}

	LuaGlue l_SetMapPaths(lua_State *L)
	{
		CheckArgumentCount(4, "SetMapPaths");
		MapManager::SetMapPaths(Lua->GetStringArgument(1, ""), Lua->GetStringArgument(2, ""), Lua->GetStringArgument(3, ""), Lua->GetStringArgument(4, ""));

		return 0;
	}

	LuaGlue l_SetMapDimensions(lua_State *L)
	{
		CheckArgumentCount(3, "SetMapDimensions");
		MapManager::SetMapDimensions(Lua->GetStringArgument(1, ""), Lua->GetNumberArgument(2, 0.0), Lua->GetNumberArgument(3, 0.0));

		return 0;
	}


	// http://pgl.yoyo.org/luai/i/lua_CFunction
	

	// MapGenerator functions
	LuaGlue l_AddGFXID(lua_State *L)
	{
		CheckArgumentCount(9, "AddGFXID");

		MapGen->AddGFXID(Lua->GetStringArgument(1, ""), Lua->GetStringArgument(2, ""), Lua->GetStringArgument(3, ""), Lua->GetStringArgument(4, ""),
			Lua->GetStringArgument(5, ""), Lua->GetStringArgument(6, ""), Lua->GetStringArgument(7, ""), Lua->GetStringArgument(8, ""),
			Lua->GetStringArgument(9, ""));

		return 0;
	}

	LuaGlue l_CreateMap(lua_State *L)
	{
		CheckArgumentCount(3, "CreateMap");
		
		//					insert tile ID					width							height
		Lua->PushNumber(MapGen->CreateMap(Lua->GetNumberArgument(1, 0.0), Lua->GetNumberArgument(2, 0.0), Lua->GetNumberArgument(3, 0.0)));

		return 1;
	}

	LuaGlue l_RegisterMap(lua_State *L)
	{
		CheckArgumentCount(1, "RegisterMap");
		MapGen->RegisterMap(Lua->GetNumberArgument(1, 0.0));
		return 0;
	}

	LuaGlue l_AddRoom(lua_State *L)
	{
		CheckArgumentCount(11, "AddRoom");

		Range x1 = {Lua->GetNumberArgument(1, 0.0), Lua->GetNumberArgument(2, 0.0)};
		Range y1 = {Lua->GetNumberArgument(5, 0.0), Lua->GetNumberArgument(6, 0.0)};
		Range x2 = {Lua->GetNumberArgument(3, 0.0), Lua->GetNumberArgument(4, 0.0)};
		Range y2 = {Lua->GetNumberArgument(7, 0.0), Lua->GetNumberArgument(8, 0.0)};

		if(Lua->IsNumber(11))
			Lua->PushNumber(MapGen->AddRoom(x1, y1, x2, y2, Lua->GetNumberArgument(9, 0.0), Lua->GetNumberArgument(10, 0.0), Lua->GetNumberArgument(11)));
		else
			Lua->PushNumber(MapGen->AddRoom(x1, y1, x2, y2, Lua->GetNumberArgument(9, 0.0), Lua->GetNumberArgument(10, 0.0), Lua->GetStringArgument(11, "")));
		return 1;
	}

	LuaGlue l_MirrorRoom(lua_State *L)
	{
		CheckArgumentCount(3, "MirrorRoom");

		Lua->PushNumber(MapGen->MirrorRoom(Lua->GetNumberArgument(1, 0.0), Lua->GetBooleanArgument(2), Lua->GetBooleanArgument(3)));
		
		return 1;
	}
	LuaGlue l_AddPath(lua_State *L)
	{
		

		

		if(Lua->GetParamaterCount() == 4)
		{
			// startID, endID, width, imgID
			Lua->PushNumber(MapGen->AddPath(Lua->GetNumberArgument(1, 0.0), Lua->GetNumberArgument(2, 0.0), Lua->GetNumberArgument(3, 0.0), Lua->GetNumberArgument(4, 0.0), 0));
			return 1;
		}
		if(Lua->GetParamaterCount() == 5)
		{
			// startID, endID, width, imgID, scatterDensity, isRiver
			if(Lua->IsNumber(5))
				Lua->PushNumber(MapGen->AddPath(Lua->GetNumberArgument(1, 0.0), Lua->GetNumberArgument(2, 0.0), Lua->GetNumberArgument(3, 0.0), Lua->GetNumberArgument(4, 0.0), Lua->GetNumberArgument(5, 0.0)));
			else
				Lua->PushNumber(MapGen->AddPath(Lua->GetNumberArgument(1, 0.0), Lua->GetNumberArgument(2, 0.0), Lua->GetNumberArgument(3, 0.0), Lua->GetNumberArgument(4, 0.0), -1, true));
			
			return 1;
		}

		if(Lua->GetParamaterCount() == 6)
		{
			// startID, endID, width, imgID, scatterDensity, isRiver
			Lua->PushNumber(MapGen->AddPath(Lua->GetNumberArgument(1, 0.0), Lua->GetNumberArgument(2, 0.0), Lua->GetNumberArgument(3, 0.0), Lua->GetNumberArgument(4, 0.0),  Lua->GetNumberArgument(5, 0.0), true));
			return 1;
		}

		CheckArgumentCount(4, "AddPath");
		CheckArgumentCount(5, "AddPath");
		CheckArgumentCount(6, "AddPath");
		return 0;
		
	}

	LuaGlue l_SaveMap(lua_State *L)
	{
		CheckArgumentCount(1, "SaveMap");
		MapGen->SaveMap(Lua->GetStringArgument(1, ""));
		return 0;
	}



	// Images

	LuaGlue l_LoadGraphic(lua_State *L)
	{
		CheckArgumentCount(2, "LoadGraphic");
		ImageManager->LoadGraphic(Lua->GetStringArgument(1, ""), Lua->GetStringArgument(2, ""));
		return 0;
	}

	LuaGlue l_AnimCreate(lua_State *L)
	{
		CheckArgumentCount(1, "AnimCreate");

		ImageManager->AnimCreate(Lua->GetStringArgument(1, ""));

		return 0;
	}

	LuaGlue l_AnimAdd(lua_State *L)
	{
		CheckArgumentCount(3, "AnimAdd");

		ImageManager->AnimAdd(Lua->GetStringArgument(1, ""), Lua->GetStringArgument(2, ""), Lua->GetStringArgument(3, ""));

		return 0;
	}

	LuaGlue l_AnimChange(lua_State *L)
	{
		CheckArgumentCount(4, "AnimChange");

		ImageManager->AnimChange(Lua->GetStringArgument(1, ""), Lua->GetStringArgument(2, ""), Lua->GetStringArgument(3, ""), Lua->GetNumberArgument(4, 0.0));

		return 0;
	}

	LuaGlue l_LoadSound(lua_State *L)
	{
		CheckArgumentCount(2, "LoadSound");

		SoundPlay->LoadSound(Lua->GetStringArgument(1, ""), Lua->GetStringArgument(2, ""));

		return 0;
	}

	LuaGlue l_AddMinimapKey(lua_State *L)
	{
		CheckArgumentCount(4, "AddMinimapKey");

		ImageManager->AddMinimapKey(Lua->GetStringArgument(1, ""), Lua->GetNumberArgument(2, 0.0), Lua->GetNumberArgument(3, 0.0), Lua->GetNumberArgument(4, 0.0));
		
		return 0;
	}

}


// Where are actually add functions
void InitLuaFunctions()
{
	using namespace LUA_FUNCTIONS;

	// first parameter is what the function name will be in lua and the second paramter is the actual function in C++
	Lua->AddFunction("DisplayMessage", l_DisplayMessage);
	Lua->AddFunction("GetWindowDimensions", l_GetWindowDimensions);
	Lua->AddFunction("AddMap", l_AddMap);
	Lua->AddFunction("SetMapPaths", l_SetMapPaths);
	Lua->AddFunction("SetMapDimensions", l_SetMapDimensions);
	Lua->AddFunction("GetFontHeight", l_GetFontHeight);
	Lua->AddFunction("GetFontWidth", l_GetFontWidth);
	Lua->AddFunction("GetImageID", l_GetImageID);

	// Map Generation functions
	Lua->AddFunction("AddGFXID", l_AddGFXID);
	Lua->AddFunction("CreateMap", l_CreateMap);
	Lua->AddFunction("RegisterMap", l_RegisterMap);
	Lua->AddFunction("AddRoom", l_AddRoom);
	Lua->AddFunction("SaveMap", l_SaveMap);
	Lua->AddFunction("AddPath", l_AddPath);
	Lua->AddFunction("MirrorRoom", l_MirrorRoom);

	// Loading functions
	Lua->AddFunction("LoadGraphic", l_LoadGraphic);
	Lua->AddFunction("AnimCreate", l_AnimCreate);
	Lua->AddFunction("AnimAdd", l_AnimAdd);
	Lua->AddFunction("AnimChange", l_AnimChange);
	Lua->AddFunction("LoadSound", l_LoadSound);
	Lua->AddFunction("AddMinimapKey", l_AddMinimapKey);
}
